package org.example.chapter1;

import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 每个Random实例里面都有一个原子性的种子变量用来记录当前的种子值，当要生成新的随机数时需要根据当前种子计算新的种子并更新回原子变量。
 * 在多线程下使用单个Random实例生成随机数时，当多个线程同时计算随机数来计算新的种子时，多个线程会竞争同一个原子变量的更新操作，
 * 由于原子变量的更新是CAS操作，同时只有一个线程会成功，所以会造成大量线程进行自旋重试，这会降低并发性能，所以ThreadLocalRandom应运而生。
 *
 * 简而言之，Random的缺点是多个线程会使用同一个原子性种子变量，而如果，每个线程都拥有独立的一个种子变量，就可避免种竞争带来的性能损耗
 */
public class S32_ThreadLocalRandom {

    public static void main(String[] args) {
        Random random = new Random();
        ThreadLocalRandom tlRandom = ThreadLocalRandom.current();

        System.out.println("main-random value:" + random.nextInt(1000));
        System.out.println("main-tlRandom value:" + tlRandom.nextInt(1000));

        new Thread(() -> {
            System.out.println("sub thread1-random value:" + random.nextInt(1000));
            System.out.println("sub thread1-tlRandom value:" + tlRandom.nextInt(1000));
        }).start();
        new Thread(() -> {
            System.out.println("sub thread2-random value:" + random.nextInt(1000));
            System.out.println("sub thread2-tlRandom value:" + tlRandom.nextInt(1000));
        }).start();
        new Thread(() -> {
            System.out.println("sub thread3-random value:" + random.nextInt(1000));
            System.out.println("sub thread3-tlRandom value:" + tlRandom.nextInt(1000));
        }).start();
    }

}
